#define _CRT_SECURE_NO_WARNINGS
#ifndef _CREATTIME
#define _CREATTIME

#include <time.h>
#include <iostream>
#include <string>
#include <sstream>
#include "ros/ros.h"
#include <json11/json11.hpp>
#include<yaml-cpp/yaml.h>
#include<dirent.h>
#include"base64/base64.h"

using namespace std;
using namespace json11;

class map_info_{

	public:
		double resolution;
		int gridHeight;
		int gridWidth;
		double originX;
		double originY;
	public:
		//构造函数
		map_info_();
		
		//读取.yaml文件
		void readMapYaml(string yaml_path,string pgm_path);
		
		//获取时间
		string getTimeStamp() ;

		//获取创建时间
		string  getCurrentTimeStr();

};

map_info_::map_info_(){
	resolution = 0.00;
	gridHeight = 0;
	gridWidth = 0;
	originX = 0.00;
	originY = 0.00;
}

void map_info_::readMapYaml(string yaml_path,string pgm_path){
	ifstream in(pgm_path, ios::binary);
	if (!in.is_open()){
		cout << "readMapYaml :: Error opening file"<<endl;;
		return ;
	}

	int i_line=0;
	string s;

	while(getline(in, s)){
		i_line++;
        if(i_line == 3){break;}
	}

	in.close();
    const size_t SIZE = 10;
    int * array = new int[SIZE];
    std::istringstream stringStream(s);

    for (size_t i = 0; (i < SIZE) && (stringStream >> array[i]); ++i){}
    cout<<array[0]<<array[1]<<endl;

	YAML::Node config = YAML::LoadFile(yaml_path);
	resolution = config["resolution"].as<double>();
	gridHeight = array[1];
	gridWidth = array[0];
	originX = config["origin"][0].as<double>();
	originY = config["origin"][1].as<double>();
	ROS_INFO("map inf: resolution: %f  height: %d  width: %d  origin: (%f, %f)\n", resolution, gridHeight, gridWidth, originX, originY);
}

string map_info_::getTimeStamp() {

	time_t timestamp;
	stringstream s;
	//char ch[16];
	s << time(&timestamp);
	return s.str();
	//strftime(ch, sizeof(ch), "%s", time(&timestamp));
}

string  map_info_::getCurrentTimeStr()
{
	time_t t = time(NULL);
	char ch[64] = { 0 };
	strftime(ch, sizeof(ch) - 1, "%Y-%m-%d %H:%M:%S", localtime(&t)); 
	return ch;
}

Json creatmap(string mapFile_t) {
	map_info_ _map;

	string _Id = _map.getTimeStamp();
	string _mapFileName = mapFile_t;
	string _createdAt =  _map.getCurrentTimeStr();
	string _tasks = "path.json";
	string _pgmName = mapFile_t + ".pgm";
	string _pngName = mapFile_t + ".png";
	string _yamlFileName = mapFile_t + ".yaml";
	string _point = "point.json";
	string _name = "NULL";
	string _obstacleFileName = "NULL";

	string yaml_path = "/root/TIC_MAP/"+_mapFileName+"/"+_yamlFileName;
	string pgm_path = "/root/TIC_MAP/"+_mapFileName+"/"+_pgmName;
	_map.readMapYaml(yaml_path,pgm_path);

	Json _mapInfo = Json::object{
		{"resolution", _map.resolution},
		{"gridHeight", _map.gridHeight},
		{"gridWidth", _map.gridWidth},		
		{"originX", _map.originX},
		{"originY", _map.originY}
	};

	Json mapJson = Json::object{
		{"Id", _Id},
		{"mapFileName", _mapFileName},
		{"createdAt", _createdAt},
		{"tasks", _tasks},
		{"pgmName", _pgmName},
		{"pngName", _pngName},
		{"yamlFileName", _yamlFileName},
		{"mapInfo", _mapInfo},
		{"points", _point},
		{"name", _name},
		{"obstacleFileName",_obstacleFileName}
	};
	
	return mapJson;
}

class get_map_info_{

	public:
		double resolution;
		int gridHeight;
		int gridWidth;
		double originX;
		double originY;
	public:
		//构造函数
		get_map_info_(){
			resolution = 0.00;
			gridHeight = 0;
			gridWidth = 0;
			originX = 0.00;
			originY = 0.00;
		}
		
		//读取.yaml文件
		void readMapYaml(string yaml_path,string pgm_path);

};

void get_map_info_::readMapYaml(string yaml_path,string pgm_path){
	ifstream in(pgm_path, ios::binary);
	if (!in.is_open()){
		cout << "readMapYaml :: Error opening file"<<endl;;
		return ;
	}

	int i_line=0;
	string s;

	while(getline(in, s)){
		i_line++;
        if(i_line == 3){break;}
	}

	in.close();
    const size_t SIZE = 10;
    int * array = new int[SIZE];
    std::istringstream stringStream(s);

    for (size_t i = 0; (i < SIZE) && (stringStream >> array[i]); ++i){}
    // cout<<array[0]<<array[1]<<endl;

	YAML::Node config = YAML::LoadFile(yaml_path);
	resolution = config["resolution"].as<double>();
	gridHeight = array[1];
	gridWidth = array[0];
	originX = config["origin"][0].as<double>();
	originY = config["origin"][1].as<double>();
	ROS_INFO("map inf: resolution: %f  height: %d  width: %d  origin: (%f, %f)\n", resolution, gridHeight, gridWidth, originX, originY);
}


Json getmapfile(string mapFile_t) {
	get_map_info_ _map;
	string path = "/root/TIC_MAP/"+mapFile_t;
	struct stat buf;
	int result;
	result=stat(path.c_str(),&buf);
	struct tm * timeSet=gmtime(&buf.st_ctime);
	char temp[50];
	strftime(temp,50,"%Y-%m-%d %H:%M:%S",timeSet);
	string _createdAt=temp;
	time_t t = mktime(timeSet);
	stringstream s;
	s << t;
	string _Id = s.str();
	string _mapFileName = mapFile_t;
	string _pgmName = mapFile_t + ".pgm";
	string _pngName = mapFile_t + ".png";
	string _yamlFileName = mapFile_t + ".yaml";
	string _tasks = "path.json";
	string _point = "point.json";
	string _name = "NULL";
	string _obstacleFileName = "NULL";

	string yaml_path = "/root/TIC_MAP/"+_mapFileName+"/"+_yamlFileName;
	string pgm_path = "/root/TIC_MAP/"+_mapFileName+"/"+_pgmName;
	// string yaml_path = "/home/lc/TIC_MAP/"+_mapFileName+"/"+_yamlFileName;
	// string pgm_path = "/home/lc/TIC_MAP/"+_mapFileName+"/"+_pgmName;
	_map.readMapYaml(yaml_path,pgm_path);

	Json _mapInfo = Json::object{
		{"resolution", _map.resolution},
		{"gridHeight", _map.gridHeight},
		{"gridWidth", _map.gridWidth},		
		{"originX", _map.originX},
		{"originY", _map.originY}
	};

	Json mapJson = Json::object{
		{"Id", _Id},
		{"mapFileName", _mapFileName},
		{"createdAt", _createdAt},
		{"tasks", _tasks},
		{"pgmName", _pgmName},
		{"pngName", _pngName},
		{"yamlFileName", _yamlFileName},
		{"mapInfo", _mapInfo},
		{"points", _point},
		{"name", _name},
		{"obstacleFileName",_obstacleFileName}
	};
	
	return mapJson;
}

Json getMapInfo(string map_name){
	get_map_info_ _map;
	string yaml_path = "/root/TIC_MAP/"+map_name+"/"+map_name + ".yaml";
	string pgm_path = "/root/TIC_MAP/"+map_name+"/"+map_name + ".pgm";
	_map.readMapYaml(yaml_path,pgm_path);

	string pgmPath = "/root/TIC_MAP/"+map_name+"/"+map_name + ".png";
	Json::object err=Json::object{};
    if( access(pgmPath.c_str(),F_OK)!=0){
        cout << "The file you expected does not exist!!!" <<pgmPath<< endl;
        return err;
    }
    fstream f;

    f.open(pgmPath.c_str(), ios::in|ios::binary);
    if(!f.is_open()){
        ROS_INFO("open file error!");
        return err;
    }
    f.seekg(0, std::ios_base::end);
    std::streampos sp = f.tellg();
    int size = sp;
    char* buffer = (char*)malloc(sizeof(char)*size);
    f.seekg(0,ios_base::beg);
    f.read(buffer,size);

    cout << "file size:" << size << endl;     
    string imgBase64 = base64_encode(buffer, size);
    cout << "img base64 encode size:" << imgBase64.size() << endl;

	Json _mapInfo = Json::object{
		{"resolution", _map.resolution},
		{"height", _map.gridHeight},
		{"width", _map.gridWidth},		
		{"originX", _map.originX},
		{"originY", _map.originY},
		{"data",imgBase64}
	};
	// cout<<_mapInfo.dump()<<endl;
	return _mapInfo;
}

Json::object handleMapJsonToApp(Json::object object_){
	string map_name = object_["mapFileName"].string_value();
	string pgmPath = "/root/TIC_MAP/"+map_name+"/"+map_name+".png";
	Json::object err=Json::object{};
    if( access(pgmPath.c_str(),F_OK)!=0){
        cout << "The file you expected does not exist!!!" <<pgmPath<< endl;
        return err;
    }
    fstream f;

    f.open(pgmPath.c_str(), ios::in|ios::binary);
    if(!f.is_open()){
        ROS_INFO("open file error!");
        return err;
    }
    f.seekg(0, std::ios_base::end);
    std::streampos sp = f.tellg();
    int size = sp;
    char* buffer = (char*)malloc(sizeof(char)*size);
    f.seekg(0,ios_base::beg);
    f.read(buffer,size);

    cout << "file size:" << size << endl;     
    string imgBase64 = base64_encode(buffer, size);
    cout << "img base64 encode size:" << imgBase64.size() << endl; 

	Json::object _mapInfo = Json::object{
		{"resolution",object_["mapInfo"]["resolution"].number_value()},
		{"gridHeight", object_["mapInfo"]["gridHeight"].int_value()},
		{"gridWidth", object_["mapInfo"]["gridWidth"].int_value()},		
		{"originX",object_["mapInfo"]["originX"].number_value()},
		{"originY", object_["mapInfo"]["originY"].number_value()},
		{"map_data",imgBase64}
	};

	Json::object mapJson = Json::object{
		{"Id", object_["Id"].string_value()},
		{"mapFileName", object_["mapFileName"].string_value()},
		{"createdAt", object_["createdAt"].string_value()},
		{"tasks", object_["tasks"].string_value()},
		{"pgmName", object_["pgmName"].string_value()},
		{"pngName", object_["pngName"].string_value()},
		{"yamlFileName", object_["yamlFileName"].string_value()},
		{"mapInfo", _mapInfo},
		{"points", object_["points"].string_value()},
		{"name", object_["name"].string_value()},
		{"obstacleFileName",object_["obstacleFileName"].string_value()}
	};
	return mapJson;
}
#endif